package main

import (
	"fmt"
	"unsafe"
)

func main() {
	fmt.Println(lengthOfLongestSubstring2("abcabcdb"))
}

func lengthOfLongestSubstring(s string) int {
	currentLongestSubs := []byte{}
	bytes := []byte(s)
	maxLen := 1
	for _, v := range bytes {
		if index, contained := contains(currentLongestSubs, v); contained {
			currentLongestSubs = append(currentLongestSubs[index+1:], v)
		} else {
			currentLongestSubs = append(currentLongestSubs, v)
		}
		//printBytes(currentLongestSubs)
		if maxLen < len(currentLongestSubs) {
			maxLen = len(currentLongestSubs)
		}
	}
	return maxLen

}

func contains(container []byte, value byte) (int, bool) {
	for k, v := range container {
		if value == v {
			return k, true
		}
	}
	return 0, false
}

func printBytes(input []byte) {
	for _, v := range input {
		fmt.Printf("%c", v)
	}
	fmt.Println()
}

func lengthOfLongestSubstring1(s string) int {
	contain := make(map[byte]int, 10)
	max := 0
	chars := []byte(s)
	lk := -1
	for rk := 0; rk < len(chars); {
		for ; rk < len(chars) && contain[chars[rk]] == 0; rk++ {
			contain[chars[rk]]++
			if max < rk-lk {
				max = rk - lk
			}
		}
		if rk < len(chars) {
			lk++
			delete(contain, chars[lk])
		}
	}
	return max
}

func lengthOfLongestSubstring2(s string) int {
	bs := string2byte(s)
	l, r := 0, 0
	maxLen := 0
	repeat := 0
	for r < len(bs) {
		repeat = repeatIndex(l, r, bs)
		if repeat == r {
			if r-l+1 > maxLen {
				maxLen = r - l + 1
			}
			r++
		} else {
			l = repeat + 1
		}
	}
	return maxLen
}

func repeatIndex(l int, r int, bs []byte) int {
	for ; l < r; l++ {
		if bs[l] == bs[r] {
			return l
		}
	}
	return l
}

func string2byte(s string) []byte {
	l := (*[2]uintptr)(unsafe.Pointer(&s))
	h := [3]uintptr{l[0], l[1], l[1]}
	return *(*[]byte)(unsafe.Pointer(&h))
}

func byte2string(b []byte) string {
	return *(*string)(unsafe.Pointer(&b))
}
